#!/bin/sh

#
# Run checks using different compilers
#
# Copyright 2023 Odin Kroeger.
#
# This file is part of suCGI.
#
# suCGI is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License,
# or (at your option) any later version.
#
# suCGI is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General
# Public License for more details.
#
# You should have received a copy of the GNU Affero General Public
# License along with suCGI. If not, see <https://www.gnu.org/licenses/>.
#

# shellcheck disable=2015


#
# Defaults
#

# Compilers to test
readonly compilers='
	gcc-14 gcc-13 gcc-12 gcc-11 gcc-10 gcc-9
	gcc-8 gcc-7 gcc-6 gcc-5 gcc-4 gcc-3
	gcc14 gcc13 gcc12 gcc11 gcc10 gcc9
	gcc8 gcc7 gcc6 gcc5 gcc4 gcc3
	gcc musl-gcc
	clang-18 clang-17 clang-16 clang-15 clang-14 clang-13
	clang-12 clang-11 clang-10 clang-9 clang-8 clang-7
	clang-6 clang-5 clang-4 clang-3 clang-2 clang-1
	clang18 clang17 clang16 clang15 clang14 clang13
	clang12 clang11 clang10 clang9 clang8 clang7
	clang6 clang5 clang4 clang3 clang2 clang1
	clang musl-clang
	tcc
	icc-2023.2 icc-2022.2 icc
	c99 cc
'

# Be quieter?
quiet=

# Be verbose?
verbose=


#
# Initialiation
#

set -Ceu
scriptsdir="$(cd -P "$(dirname -- "$0")" && pwd)"
: "${scriptsdir:?}"
readonly scriptsdir
srcdir="$(dirname -- "$scriptsdir")"
: "${srcdir:?}"
readonly srcdir
# shellcheck disable=1091
. "$scriptsdir/../libutil.sh"	|| exit
init				|| exit
tmpdir tmp "$srcdir"		|| exit


#
# Constants
#

# Default options for icc
# shellcheck disable=2034
readonly icc_flags='-diag-disable=161,10441 -std=c99 -O2 -s'

# Current working directory
wd="$(pwd)" || exit
: "${wd:?}"
readonly wd


#
# Options
#

OPTIND=1 OPTARG='' opt=''
# shellcheck disable=2034
while getopts dhqv opt; do
	# shellcheck disable=2154
	case $opt in
	(h) exec cat <<EOF ;;
$progname - run checks using different C compilers

Usage:  $progname [-d] [-q] [-v] [cc ...]
        $progname -h

Options:
    -d  Enable debugging mode.
    -q  Be quieter.
    -v  Show, rather than log, test output.
EOF
	(d) set -x ;;
	(q) quiet=y ;;
	(v) verbose=y ;;
	(*) exit 2
	esac
done
shift $((OPTIND - 1))
unset opt

# shellcheck disable=2086
[ $# -eq 0 ] && set -- $compilers


#
# Source tree
#

warn -q 'Copying source tree ...'
cd "$srcdir" || exit
logged -d"$wd" make distar="$TMPDIR/dist.tgz" dist=dist "$TMPDIR/dist.tgz"
cd "$TMPDIR" || exit
tar xzf dist.tgz
cd dist || exit
cp config.h.tpl config.h


#
# Main
#

nccs=0 failures=
for cc
do
	absfname="$(command -v "$cc" 2>/dev/null)" || continue

	if [ "$cc" != c99 ]
	then
		i=0
		while [ "$i" -lt "$nccs" ]
		do
			eval seencc="\${cc_$i-}"
			if cmp "${absfname:?}" "${seencc:?}" >/dev/null 2>&1
			then
				# shellcheck disable=2154
				warn '%s has already been checked as %s' \
				     "$cc" "${seencc##*/}"
				continue 2
			fi
			i=$((i + 1))
		done

		eval "cc_$nccs"='$absfname'
		nccs=$((nccs + 1))
	fi

	warn 'Checking %s ... ' "$cc"

	[ -e Makefile ] && logged -d"$wd" make distclean

	eval "cflags=\${${cc%%[!a-z]*}_flags-}"
	# shellcheck disable=2154
	cp Makefile.in Makefile

	logged -d"$wd" -l"$cc.log" make clean all check ||
		failures="$failures$cc (w/o configuration), "

	for env in conf/*.env
	do
		case $env in
		('*.env')	break ;;
		('local.env')	continue ;;
		esac

		[ -e Makefile ] && logged -d"$wd" make distclean
		logged -d"$wd" \
			./configure CC="$cc" --force --quiet --conf="$env"

		logged -d"$wd" -l"$cc.log" make clean all check ||
			failures="$failures$cc (w/ $env), "
	done
done

if [ "$failures" ]
then err -s70 'Failures: %s' "${failures%, }"
else warn -q 'All compilers passed'
fi

